# -*- coding: utf-8 -*-
# @Author	: brotherbaby
# @Date		: 2023/10/25 9:49
# @Last Modified by:   brotherbaby
# @Last Modified time: 2023/10/25 9:49
# Thanks for your comments!

import copy
import json
import logging
import time
import traceback

import requests
import sqlalchemy
from flask import request
from sqlalchemy import func

from src.config import CONF
from src.db_proxy.connect import DbConnector
from src.db_proxy.models.operation import Operation
from src.db_proxy.models.order import Order
from src.db_proxy.models.person import Person
from src.db_proxy.models.shoes_detail import ShoesDetail
from src.db_proxy.models.site import Site
from src.db_proxy.models.user import User
from src.tornadoweb_app import app
from .utils import get_memory_token, verify_token, get_weixin_token

logger = logging.getLogger(__name__)


@app.route("/wechat_milangze/login", methods=["GET"])
def login_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.args
        if not params.get("code") or not params.get("client_type"):
            resp.update({"code": -1, "message": "invalid input: code or client_type"})
            return json.dumps(resp)
        milangze_conf = CONF.app.get(params["client_type"])
        req_url = CONF.interfaces.get(
            "weixin_url") + f"/sns/jscode2session?appid={milangze_conf.get('app_id')}&secret={milangze_conf.get('app_secret')}&js_code={params.get('code')}&grant_type=authorization_code"
        res = requests.get(req_url)
        if res.status_code != 200:
            logger.error("request weixin to login failed with error: %s", str(res))
            resp.update({"code": -1, "message": f"request weixin to login failed with error: {str(res)}"})
            return json.dumps(resp)
        res_data = json.loads(res.text)
        if not res_data.get("openid"):
            logger.error("request weixin to login failed with error: %s", res.text)
            resp.update({"code": -1, "message": f"request weixin to login failed with error: {res.text}"})
            return json.dumps(resp)
        res_data.update({"access_token": get_memory_token(params.get("client_type"))})
        db_con = DbConnector()
        session = db_con.get_session()
        user_obj = session.query(User).filter(User.openid == res_data.get("openid"), User.obsoleted == False).first()
        if not user_obj:
            user_obj = User(
                openid=res_data.get("openid")
            )
            session.add(user_obj)
        res_data["user_id"] = user_obj.id
        resp["data"] = res_data
        session.commit()
        db_con.close_session(session)
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    return json.dumps(resp)


@app.route("/wechat_milangze/query_user_info", methods=["GET"])
def query_user_info_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.args
        for f in ["openid", "client_type", "access_token"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        req_url = CONF.interfaces.get("weixin_url") + f"/sns/userinfo"
        succ, res_data = common_request_weixin("GET", req_url, params={
            "access_token": params.get("access_token"),
            "openid": params.get('openid'),
            "ang": "zh_CN"
        }, client_type=params["client_type"])
        if not succ:
            logger.error("request weixin to query_user_info failed with error: %s", str(res_data))
            resp.update(
                {"code": -1, "message": f"request weixin to query_user_info failed with error: {str(res_data)}"})
            return json.dumps(resp)
        resp["data"] = res_data
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    return json.dumps(resp)


@app.route("/wechat_milangze/get_phone_number", methods=["GET"])
def query_phone_number_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.args
        for f in ["code", "client_type", "access_token"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        req_url = CONF.interfaces.get("weixin_url") + "/wxa/business/getuserphonenumber"
        succ, res_data = common_request_weixin("POST", req_url, params={
            "access_token": params.get("access_token"),
            "code": params.get('code')
        }, client_type=params["client_type"])
        if not succ:
            logger.error("request weixin to query_user_info failed with error: %s", str(res_data))
            resp.update(
                {"code": -1, "message": f"request weixin to query_user_info failed with error: {str(res_data)}"})
            return json.dumps(resp)
        resp["data"] = res_data
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    return json.dumps(resp)


@app.route("/wechat_milangze/shoes_commit", methods=["POST"])
def shoes_commit_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.get_json()
        logger.info("/wechat_milangze/shoes_commit, params: %s", params)
        for f in ["name", "phone", "shoes", "site_no", "access_token"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        for s in params.get("shoes", []):
            exists_s = session.query(ShoesDetail).filter(ShoesDetail.shoes_ecode == s.get("shoes_ecode")).first()
            if exists_s:
                resp.update({"code": -1, "message": "编码“%s”的鞋已经提交过，请不要重复提交" % s.get("shoes_ecode")})
                return json.dumps(resp)
        person_obj = session.query(Person).filter(Person.phone == params.get("phone"),
                                                  Person.obsoleted == False).first()
        if not person_obj:
            person_obj = Person(
                name=params.get("name"),
                phone=params.get("phone")
            )
            session.add(person_obj)
            session.flush()
        site = session.query(Site).filter(Site.no == params.get("site_no")).first()
        if not site:
            session.add(Site(
                no=params.get("site_no"),
                name=params.get("site_name")
            ))
        order = Order(
            user_id=params.get("user_id"),
            name=params.get("name"),
            person_id=person_obj.id,
            site_no=params.get("site_no"),
            number=params.get("number"),
            commit_time=params.get("commit_time"),
            item_category=params.get("item_category") or 1,
            payment_channel=params.get("payment_channel") or 1,
            status=0,
            remark=params.get("remark")
        )
        session.add(order)
        session.flush()
        shoes_objs = []
        operations_objs = []
        for s in params.get("shoes", []):
            shoes_objs.append(ShoesDetail(
                order_id=order.id,
                shoes_ecode=s.get("shoes_ecode"),
                pic_url=[s.get("pic_url")],
                status=0,
                remark=s.get("remark", "")
            ))
            operations_objs.append(Operation(
                order_id=order.id,
                shoes_ecode=s.get("shoes_ecode"),
                operation_type=0,  # 提交
                operation_time=int(time.time() * 1000),
                operator=params.get("operator", "")
            ))
        if shoes_objs:
            session.add_all(shoes_objs)
        if operations_objs:
            session.add_all(operations_objs)
        session.commit()
        db_conn.close_session(session)
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    return json.dumps(resp)


@app.route("/wechat_milangze/get_commit_record", methods=["GET"])
def get_commit_record_api():
    resp = {"code": 0, "message": "success"}
    try:
        req_params = request.args
        params = req_params.to_dict()
        for f in ["client_type", "access_token"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        if params.get("shoes_ecode"):
            sd = session.query(ShoesDetail).filter(ShoesDetail.shoes_ecode == params.get("shoes_ecode")).first()
            if not sd:
                resp["data"] = {"total": 0, "records": []}
                return json.dumps(resp)
            shoes_dats_count = session.query(func.count(ShoesDetail.id)).filter(
                ShoesDetail.order_id == sd.order_id, ShoesDetail.status == 2).scalar()
            cr_p = session.query(Order, Person, Site).filter(Order.id == sd.order_id).join(Person).join(Site).first()
            if not cr_p:
                resp["data"] = {"total": 0, "records": []}
                return json.dumps(resp)
            cr, p, site = cr_p
            one_data = cr.get_fields()
            one_data["person"] = p.get_fields()
            one_data["site"] = site.get_fields()
            one_data["shoes"] = [sd.get_fields()]
            one_data["ex_count"] = shoes_dats_count
            operations = session.query(Operation).filter(
                Operation.shoes_ecode == params.get("shoes_ecode"), Operation.obsoleted == False).all()
            one_data["operations"] = [op.get_fields() for op in operations]
            resp["data"] = {
                "total": 1,
                "records": [one_data]
            }
            return json.dumps(resp)
        q = []
        if params.get("openid") or params.get("user_id"):
            p_user_id = params.get("user_id")
            if not p_user_id:
                user_obj = session.query(User).filter(User.openid == params.get("openid"),
                                                      User.obsoleted == False).first()
                if not user_obj:
                    resp.update({"data": {"total": 0, "records": []}})
                    return json.dumps(resp)
                p_user_id = user_obj.id
            q.append(Order.user_id == int(p_user_id))
        if params.get("phone"):
            per_objs = session.query(Person).filter(Person.phone.ilike(f"{params.get('phone')}%"),
                                                    Person.obsoleted == False).all()
            if not per_objs:
                resp.update({"data": {"total": 0, "records": []}})
                return json.dumps(resp)
            q.append(Order.person_id.in_([i.id for i in per_objs]))
        if params.get("name"):
            q.append(Order.name.ilike(f"%{params.get('name')}%"))
        if params.get("site_no"):
            q.append(Order.site_no == params.get("site_no"))
        if params.get("site_name"):
            sites_obj = session.query(Site).filter(Site.name.ilike(f"%{params.get('site_name')}%")).all()
            if not sites_obj:
                resp["data"] = {"total": 0, "records": []}
                return json.dumps(resp)
            q.append(Order.site_no.in_([item.no for item in sites_obj]))
        q_sd = []
        if params.get("status"):
            if not isinstance(params.get("status"), list):
                params["status"] = [params.get("status")]
            params["status"] = [int(i) for i in params["status"]]
            q_sd.append(ShoesDetail.status.in_(params["status"]))
            # q.append(Order.status.in_([int(i) for i in params["status"]]))
        if params.get("item_category"):
            if not isinstance(params.get("item_category"), list):
                params["item_category"] = [params.get("item_category")]
            params["item_category"] = [int(i) for i in params["item_category"]]
            if 1 in params["item_category"]:
                q.append(sqlalchemy.or_(
                    Order.item_category.in_(params["item_category"]),
                    Order.item_category.is_(None)
                ))
            else:
                q.append(Order.item_category.in_(params["item_category"]))
        if params.get("payment_channel"):
            if not isinstance(params.get("payment_channel"), list):
                params["payment_channel"] = [params.get("payment_channel")]
            params["payment_channel"] = [int(i) for i in params["payment_channel"]]
            if 1 in params["payment_channel"]:
                q.append(sqlalchemy.or_(
                    Order.payment_channel.in_(params["payment_channel"]),
                    Order.payment_channel.is_(None)
                ))
            else:
                q.append(Order.payment_channel.in_(params["payment_channel"]))
        if params.get("commit_time_start") and params.get("commit_time_end"):
            q.append(Order.commit_time.between(int(params["commit_time_start"]), int(params["commit_time_end"])))
        if not int(params.get("query_all", 0)):
            offset = int(params.get("page_size", 10)) * (int(params.get("page", 1)) - 1)
            if q_sd:
                order_dats_count = session.query(func.count(func.distinct(Order.id))).filter(*q) \
                    .join(ShoesDetail).filter(*q_sd).scalar()
                order_dats_id_objs = session.query(func.distinct(Order.id), Order.commit_time).filter(*q) \
                    .join(ShoesDetail).filter(*q_sd) \
                    .order_by(Order.commit_time.desc()) \
                    .offset(offset).limit(int(params.get("page_size", 10))).all()
                order_dats_ids = [i[0] for i in order_dats_id_objs]
                order_dats = session.query(Order, Person, Site).filter(Order.id.in_(order_dats_ids)) \
                    .order_by(Order.commit_time.desc()) \
                    .outerjoin(Person).outerjoin(Site).all()
            else:
                order_dats_count = session.query(func.count(Order.id)).filter(*q).scalar()
                order_dats = session.query(Order, Person, Site).filter(*q).order_by(Order.commit_time.desc()).join(
                    Person).join(Site).offset(offset).limit(int(params.get("page_size", 10))).all()
            # .join(Person, Order.person_id == Person.id)
        else:
            order_dats = session.query(Order, Person, Site).filter(*q).order_by(Order.commit_time.desc()).join(
                Person).join(Site).all()
            order_dats_count = len(order_dats)
        res_data = []
        for order_dat in order_dats:
            order, person, site = order_dat
            q_shoes = [ShoesDetail.order_id == order.id]
            if params.get("status"):
                q_shoes.append(ShoesDetail.status.in_(params.get("status")))
            sds = session.query(ShoesDetail).filter(*q_shoes).all()
            if not sds:
                continue
            sds_list = []
            sd_ex_count = 0
            for sd in sds:
                sd_item = sd.get_fields()
                if sd.status == 2:
                    sd_ex_count += 1
                operations = session.query(Operation).filter(
                    Operation.shoes_ecode == sd.shoes_ecode, Operation.obsoleted == False).all()
                sd_item["operations"] = [op.get_fields() for op in operations]
                sds_list.append(sd_item)

            res_data_item = copy.deepcopy(order.get_fields())
            res_data_item.update({
                "person": person.get_fields(),
                "site": site.get_fields(),
                "shoes": sds_list,
                "ex_count": sd_ex_count
            })
            res_data.append(res_data_item)
        resp["data"] = {
            "total": order_dats_count,
            "records": res_data
        }
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            db_conn.close_session(session)
    return json.dumps(resp)


@app.route("/wechat_milangze/get_operations", methods=["GET"])
def get_operations_api():
    resp = {"code": 0, "message": "success"}
    try:
        req_params = request.args
        params = req_params.to_dict()
        for f in ["client_type", "access_token"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        if not (params.get("shoes_ecode") or params.get("order_id")):
            resp.update({"code": -1, "message": "invalid input"})
            return json.dumps(resp)
        q = [Operation.obsoleted == False]
        if params.get("shoes_ecode"):
            q.append(Operation.shoes_ecode == params.get("shoes_ecode"))
        if params.get("order_id"):
            q.append(Operation.order_id == int(params.get("order_id")))
        operations = session.query(Operation).filter(*q).all()
        resp["data"] = [op.get_fields() for op in operations]
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            db_conn.close_session(session)
    return json.dumps(resp)


@app.route("/wechat_milangze/add_pic", methods=["POST"])
def add_pic_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.get_json()
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        for f in ["shoes_ecode", "pic_url"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        sd = session.query(ShoesDetail).filter(ShoesDetail.shoes_ecode == params["shoes_ecode"],
                                               ShoesDetail.status.in_([0, 7])).first()
        if not sd:
            resp.update({"code": -1, "message": "未找到该鞋码：%s" % params["shoes_ecode"]})
            return json.dumps(resp)
        sd_pic_url = params.get("pic_url")
        if not isinstance(sd_pic_url, list):
            sd_pic_url = [sd_pic_url]
        sd_pic_url.insert(0, sd.pic_url)
        session.query(ShoesDetail).filter(ShoesDetail.id == sd.id).update({"pic_url": ",".join(sd_pic_url)})
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            session.commit()
            db_conn.close_session(session)
    return json.dumps(resp)


@app.route("/wechat_milangze/receiving", methods=["POST"])
def receiving_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.get_json()
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        for f in ["shoes_ecode"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        if isinstance(params.get("shoes_ecode"), str):
            params["shoes_ecode"] = [params.get("shoes_ecode")]
        for i_shoes_ecode in params["shoes_ecode"]:
            sd = session.query(ShoesDetail).filter(ShoesDetail.shoes_ecode == i_shoes_ecode,
                                                   ShoesDetail.status == 0).first()
            if not sd:
                resp.update({"code": -1, "message": "未找到该鞋码或状态不正确：%s" % i_shoes_ecode})
                return json.dumps(resp)
            session.query(ShoesDetail).filter(ShoesDetail.id == sd.id).update({"status": 7})
            session.flush()
            cur_sds = session.query(ShoesDetail).filter(
                ShoesDetail.order_id == sd.order_id,
                ShoesDetail.id != sd.id,
                ShoesDetail.status == 0
            ).all()
            # 说明还有鞋子未收件，则不修改order的状态
            if not cur_sds:
                session.query(Order).filter(Order.id == sd.order_id).update({"status": 7})
            session.add(Operation(
                order_id=sd.order_id,
                shoes_ecode=i_shoes_ecode,
                operation_type=7,  # 收件
                operation_time=int(time.time() * 1000),
                operator=params.get("operator", "")
            ))
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            session.commit()
            db_conn.close_session(session)
    return json.dumps(resp)


@app.route("/wechat_milangze/enter_factory", methods=["POST"])
def enter_factory_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.get_json()
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        for f in ["shoes_ecode"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        sd = session.query(ShoesDetail).filter(
            ShoesDetail.shoes_ecode == params["shoes_ecode"]
        ).first()
        if not sd:
            resp.update({"code": -1, "message": "未找到该鞋码或状态不正确：%s" % params["shoes_ecode"]})
            return json.dumps(resp)
        session.query(ShoesDetail).filter(ShoesDetail.id == sd.id).update({"status": 1})
        session.flush()
        cur_sds = session.query(ShoesDetail).filter(
            ShoesDetail.order_id == sd.order_id,
            ShoesDetail.id != sd.id,
            ShoesDetail.status.in_([0, 7])
        ).all()
        # 说明还有鞋子未入厂，则不修改order的状态
        if not cur_sds:
            session.query(Order).filter(Order.id == sd.order_id, Order.status != 1).update({"status": 1})
        session.add(Operation(
            order_id=sd.order_id,
            shoes_ecode=params["shoes_ecode"],
            operation_type=1,  # 入厂
            operation_time=int(time.time() * 1000),
            operator=params.get("operator", "")
        ))
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            session.commit()
            db_conn.close_session(session)
    return json.dumps(resp)


@app.route("/wechat_milangze/leave_factory", methods=["POST"])
def leave_factory_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.get_json()
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        for f in ["shoes_ecode"]:
            if not params.get(f):
                logger.error("lack %s", f)
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        sd = session.query(ShoesDetail).filter(ShoesDetail.shoes_ecode == params["shoes_ecode"]).first()
        if not sd:
            resp.update({"code": -1, "message": "未找到该鞋码或状态不正确：%s" % params["shoes_ecode"]})
            return json.dumps(resp)
        session.query(ShoesDetail).filter(ShoesDetail.id == sd.id).update({"status": 2})
        session.flush()
        cur_sds = session.query(ShoesDetail).filter(
            ShoesDetail.order_id == sd.order_id,
            ShoesDetail.id != sd.id,
            ShoesDetail.status.in_([0, 7, 1])
        ).all()
        # 说明还有鞋子未出厂，则不修改order的状态
        if not cur_sds:
            session.query(Order).filter(Order.id == sd.order_id, Order.status != 1).update({"status": 2})
        session.add(Operation(
            order_id=sd.order_id,
            shoes_ecode=params["shoes_ecode"],
            operation_type=2,  # 出厂
            operation_time=int(time.time() * 1000),
            operator=params.get("operator", "")
        ))
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            session.commit()
            db_conn.close_session(session)
    return json.dumps(resp)


@app.route("/wechat_milangze/shoes_return", methods=["POST"])
def shoes_return_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.get_json()
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        sd = session.query(ShoesDetail).filter(ShoesDetail.shoes_ecode == params.get("shoes_ecode")).first()
        if not sd:
            resp.update({"code": -1, "message": "未找到该鞋码：%s" % params.get("shoes_ecode")})
            return json.dumps(resp)
        session.query(ShoesDetail).filter(ShoesDetail.id == sd.id).update({"status": 3})
        session.flush()
        cur_sds = session.query(ShoesDetail).filter(
            ShoesDetail.order_id == sd.order_id,
            ShoesDetail.id != sd.id,
            ShoesDetail.status.in_([0, 7, 1, 2])
        ).all()
        # 说明还有鞋子未退回，则不修改order的状态
        if not cur_sds:
            session.query(Order).filter(Order.id == sd.order_id).update({"status": 3})
        session.add(Operation(
            order_id=sd.order_id,
            shoes_ecode=params["shoes_ecode"],
            operation_type=3,  # 退回
            operation_time=int(time.time() * 1000),
            operator=params.get("operator", "")
        ))
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            session.commit()
            db_conn.close_session(session)
    return json.dumps(resp)


@app.route("/wechat_milangze/delivery_receiving", methods=["POST"])
def delivery_receiving_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.get_json()
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        if isinstance(params.get("shoes_ecode"), str):
            params["shoes_ecode"] = [params.get("shoes_ecode")]
        for i_shoes_ecode in params["shoes_ecode"]:
            sd = session.query(ShoesDetail).filter(ShoesDetail.shoes_ecode == i_shoes_ecode).first()
            if not sd:
                resp.update({"code": -1, "message": "未找到该鞋码：%s" % i_shoes_ecode})
                continue
            session.query(ShoesDetail).filter(ShoesDetail.id == sd.id).update({"status": 4})
            session.flush()
            cur_sds = session.query(ShoesDetail).filter(
                ShoesDetail.order_id == sd.order_id,
                ShoesDetail.id != sd.id,
                ShoesDetail.status.in_([0, 7, 1, 2, 3])
            ).all()
            # 说明还有鞋子配送中，则不修改order的状态
            if not cur_sds:
                session.query(Order).filter(Order.id == sd.order_id).update({"status": 4})
            session.add(Operation(
                order_id=sd.order_id,
                shoes_ecode=i_shoes_ecode,
                operation_type=4,  # 接收配送
                operation_time=int(time.time() * 1000),
                operator=params.get("operator", "")
            ))
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            session.commit()
            db_conn.close_session(session)
    return json.dumps(resp)


def common_request_weixin(method, url, params, client_type, try_count=0):
    res = None
    if method == "GET":
        res = requests.get(url, params=params)
    elif method == "POST":
        cur_url = url + "?access_token=%s" % params.get("access_token")
        del params["access_token"]
        res = requests.post(cur_url, json=params)
    if not res:
        return False, None
    if res.status_code != 200:
        logger.error("request %s failed with error: %s", url, str(res))
        return False, None
    res_data = json.loads(res.text)
    if res_data.get("errcode") in [40001, 42001]:
        if try_count > 0:
            return False, None
        logger.warning("got invalid access_token.")
        new_token = get_weixin_token(client_type)
        params["access_token"] = new_token
        return common_request_weixin(method, url, params, client_type, try_count + 1)
    return True, res_data


@app.route("/wechat_milangze/devops_create_sites", methods=["GET"])
def devops_create_sites_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.args
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        from src.db_proxy.models.station import Station
        stas = session.query(Station).filter().all()
        sis = []
        for sta in stas:
            sis.append(Site(
                no=sta.site_no,
                name=sta.station_name,
                address=sta.station_address,
                contact=sta.station_charge,
                site_phone=sta.station_phone,
                district=sta.station_district
            ))
        session.add_all(sis)
        session.commit()
        db_conn.close_session(session)
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    return json.dumps(resp)
